#include "server.h"

Server::Server(QObject* parent) : QTcpServer(parent) {
    this->commands.insert("authorization", new AuthorizationCommand());
    this->commands.insert("register", new RegisterCommand());
    this->commands.insert("roomsList", new RoomListCommand());
    this->commands.insert("joinRoom", new JoinRoomCommand());
    this->commands.insert("getUsers", new GetUsersCommand());
    this->commands.insert("sendMessage", new SendMessageCommand());
    this->commands.insert("getMessages", new GetMessagesCommand());
    this->commands.insert("leave", new LeaveCommand());
}

Server::~Server() {
    this->stop();
}

bool Server::start(int port) {
    return this->listen(QHostAddress::Any, port);
}

void Server::stop() {
    this->close();
}

void Server::incomingConnection(int socketDescriptor) {
    QTcpSocket *client = new QTcpSocket(this);
    client->setSocketDescriptor(socketDescriptor);
    clients.insert(client);

    AccessLog::append(QString("Connected: ").append(client->peerAddress().toString()));

    connect(client, SIGNAL(readyRead()), this, SLOT(readyRead()));
    connect(client, SIGNAL(disconnected()), this, SLOT(disconnected()));
}

void Server::processRequest(QString xml, QTcpSocket *client) {
    QDomDocument xmlDocument;
    QString response;
    if (!xmlDocument.setContent(xml)) {
        response = "<error><result>WRONG_XML</result></error>";
    } else {
        QString command = xmlDocument.firstChild().toElement().tagName();
        ServerCommand* executor = this->commands.value(command, new WrongCommand());
        response = executor->run(xmlDocument).toString();
    }
    client->write(response.append("\n").toUtf8());
}

void Server::readyRead() {
    QString xml = "";
    QTcpSocket *client = (QTcpSocket*)sender();
    while(client->canReadLine()) {
        QString line = QString::fromUtf8(client->readLine()).trimmed();
        xml.append(line);
    }
    AccessLog::append(xml.append("\n"));
    this->processRequest(xml, client);
}

void Server::disconnected() {
    QTcpSocket *client = (QTcpSocket*)sender();
    AccessLog::append(QString("Disconnected: ").append(client->peerAddress().toString()));
    this->clients.remove(client);
    users.remove(client);
}
